# ======================================================================
# Copyright TOTAL / CERFACS / LIRMM (08/2020)
# Contributor: Adrien Suau (<adrien.suau@cerfacs.fr>
#                           <adrien.suau@lirmm.fr>)
#
# This software is governed by the CeCILL-B license under French law and
# abiding  by the  rules of  distribution of free software. You can use,
# modify  and/or  redistribute  the  software  under  the  terms  of the
# CeCILL-B license as circulated by CEA, CNRS and INRIA at the following
# URL "http://www.cecill.info".
#
# As a counterpart to the access to  the source code and rights to copy,
# modify and  redistribute granted  by the  license, users  are provided
# only with a limited warranty and  the software's author, the holder of
# the economic rights,  and the  successive licensors  have only limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading,  using, modifying and/or  developing or reproducing  the
# software by the user in light of its specific status of free software,
# that  may mean  that it  is complicated  to manipulate,  and that also
# therefore  means that  it is reserved for  developers and  experienced
# professionals having in-depth  computer knowledge. Users are therefore
# encouraged  to load and  test  the software's  suitability as  regards
# their  requirements  in  conditions  enabling  the  security  of their
# systems  and/or  data to be  ensured and,  more generally,  to use and
# operate it in the same conditions as regards security.
#
# The fact that you  are presently reading this  means that you have had
# knowledge of the CeCILL-B license and that you accept its terms.
# ======================================================================


from qat.lang.AQASM.routines import QRoutine
from qat.lang.AQASM.misc import build_gate

from qaths.applications.wave_equation.oracles import (
    get_oracle_dirichlet1_1d_wave_equation,
    get_oracle_dirichlet2_1d_wave_equation,
)
from qaths.routines.comparator import arithmetic_compare
from qaths.routines.arithmetic import add_const_carry, sub_const_carry, high_bit_compute
from qaths.applications.wave_equation.utils import (
    compute_qubit_number_from_considered_points_1d,
)


def get_linking_set(discretisation_point_number: int):
    n = compute_qubit_number_from_considered_points_1d(discretisation_point_number - 2)

    @build_gate("oracle1", [], arity=2 * n + 2)
    def oracle1() -> QRoutine:
        parametrised_gate = get_oracle_dirichlet1_1d_wave_equation(
            n, discretisation_point_number
        )
        rout = QRoutine()
        qubits = rout.new_wires(parametrised_gate.arity)
        rout.apply(parametrised_gate, qubits)
        return rout

    @build_gate("oracle2", [], arity=2 * n + 2)
    def oracle2() -> QRoutine:
        parametrised_gate = get_oracle_dirichlet2_1d_wave_equation(
            n, discretisation_point_number
        )
        rout = QRoutine()
        qubits = rout.new_wires(parametrised_gate.arity)
        rout.apply(parametrised_gate, qubits)
        return rout

    linking_set = [
        oracle1,
        oracle2,
        arithmetic_compare,
        high_bit_compute,
        add_const_carry,
        sub_const_carry,
    ]

    return linking_set
